﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024-2025 LiLong                                              **
**  This file is part of OpenVisaApplication.                                   **
**                                                                              **
**  OpenVisaApplication is free software: you can redistribute it and/or modify **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  OpenVisaApplication is distributed in the hope that it will be useful,      **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with OpenVisaApplication. If not, see <https://www.gnu.org/licenses/>.**
**********************************************************************************/
#include "IOTraceView.h"
#include "IOTraceModel.h"

#include <IOTraceService/IOTraceService.h>
#include <QCustomUi/QCtmInputDialog.h>
#include <QCustomUi/QCtmMessageBox.h>
#include <QCustomUi/QCtmTitleBar.h>

#include <QScrollBar>
#include <QToolBar>

struct IOTraceView::Impl
{
    IOTraceModel* model;
    QToolBar* toolBar;
    QAction* startAction;
    QAction* stopAction;
    QAction* clearAction;
    QAction* pinAction;
    QAction* settingsAction;
    QAction* copyAction;
    bool autoScroll { false };
};

IOTraceView::IOTraceView(QWidget* parent) : QCtmWindow(parent), m_impl(std::make_unique<Impl>())
{
    ui.setupUi(centralWidget());
    QIcon pin;
    pin.addFile(":/OpenVisaApplication/Resources/PinOff.svg");
    pin.addFile(":/OpenVisaApplication/Resources/PinOn.svg", {}, QIcon::Mode::Normal, QIcon::State::On);
    m_impl->pinAction = titleBar()->addAction(pin, "");
    m_impl->pinAction->setCheckable(true);
    connect(m_impl->pinAction,
            &QAction::toggled,
            this,
            [this](bool on)
            {
                this->close();
                setWindowFlag(Qt::WindowStaysOnTopHint, on);
                this->show();
            });
    m_impl->settingsAction = titleBar()->addAction(QIcon(":/OpenVisaApplication/Resources/Settings.svg"), "");
    connect(m_impl->settingsAction, &QAction::triggered, this, &IOTraceView::onSettingsAction);

    ui.toolBarLayout->addWidget(m_impl->toolBar = new QToolBar(this));
    ui.tableView->setModel(m_impl->model = new IOTraceModel(this));
    m_impl->startAction = m_impl->toolBar->addAction(QIcon(":/OpenVisaApplication/Resources/Start.svg"), "", QKeySequence(Qt::Key_F5));
    m_impl->stopAction =
        m_impl->toolBar->addAction(QIcon(":/OpenVisaApplication/Resources/Stop.svg"), "", QKeySequence(Qt::Key_Shift | Qt::Key_F5));
    m_impl->stopAction->setEnabled(false);
    m_impl->toolBar->addSeparator();
    m_impl->clearAction = m_impl->toolBar->addAction(QIcon(":/OpenVisaApplication/Resources/Clear.svg"), "");
    connect(m_impl->startAction, &QAction::triggered, this, &IOTraceView::onStartAction);
    connect(m_impl->stopAction, &QAction::triggered, this, &IOTraceView::onStopAction);
    connect(m_impl->clearAction, &QAction::triggered, m_impl->model, &IOTraceModel::clear);
    connect(
        &IOTrace::IOTraceService::instance(), &IOTrace::IOTraceService::started, this, [this] { m_impl->stopAction->setEnabled(true); });
    connect(&IOTrace::IOTraceService::instance(),
            &IOTrace::IOTraceService::stoped,
            this,
            [this]
            {
                m_impl->startAction->setEnabled(true);
                m_impl->stopAction->setEnabled(false);
            });
    connect(&IOTrace::IOTraceService::instance(), &IOTrace::IOTraceService::dataArrived, m_impl->model, &IOTraceModel::addData);

    ui.tableView->setColumnWidth(0, 200);
    ui.tableView->setColumnWidth(1, 50);
    ui.tableView->setColumnWidth(2, 250);
    ui.tableView->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui.tableView, &QTableView::customContextMenuRequested, this, &IOTraceView::onCustomContextMenuRequested);
    m_impl->copyAction = ui.tableView->addAction(QIcon(":/OpenVisaApplication/Resources/Copy.svg"), u8"复制", QKeySequence::Copy);
    connect(m_impl->copyAction, &QAction::triggered, this, &IOTraceView::onCopyAction);
    connect(m_impl->model,
            &IOTraceModel::rowsAboutToBeInserted,
            this,
            [&] { m_impl->autoScroll = ui.tableView->verticalScrollBar()->value() == ui.tableView->verticalScrollBar()->maximum(); });
    connect(m_impl->model,
            &IOTraceModel::rowsInserted,
            this,
            [&]
            {
                if (m_impl->autoScroll)
                {
                    ui.tableView->scrollToBottom();
                }
            });
}

IOTraceView::~IOTraceView() {}

void IOTraceView::onStartAction()
{
    m_impl->startAction->setEnabled(false);
    IOTrace::IOTraceService::instance().start();
}

void IOTraceView::onStopAction()
{
    m_impl->stopAction->setEnabled(false);
    IOTrace::IOTraceService::instance().stop();
}

void IOTraceView::onSettingsAction()
{
    bool ok = false;
    auto port =
        QCtmInputDialog::getInt(this, u8"IO Trace 端口号设置", u8"端口号", IOTrace::IOTraceService::instance().port(), 0, 65535, 1, &ok);
    if (ok)
    {
        IOTrace::IOTraceService::instance().setPort(port);
        QCtmMessageBox::information(this, u8"提示", u8"设置端口号成功，请停止 IO Trace 再重新开始。");
    }
}

void IOTraceView::onCustomContextMenuRequested(const QPoint& pos)
{
    auto index = ui.tableView->indexAt(pos);
    if (index.isValid())
    {
        QMenu menu(ui.tableView);
        menu.addAction(m_impl->copyAction);
        menu.exec(QCursor::pos());
    }
}

void IOTraceView::onCopyAction()
{
    auto selectionModel = ui.tableView->selectionModel();
    auto rows           = selectionModel->selectedRows();
    if (rows.isEmpty())
        return;
    m_impl->model->copy(rows);
}

void IOTraceView::closeEvent(QCloseEvent* event)
{
    IOTrace::IOTraceService::instance().stop();
    QCtmWindow::closeEvent(event);
}
